package com.tbynet.jwp.service.task;

import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.tbynet.jwp.service.dto.response.TermResponse;
import com.tbynet.jwp.service.support.TermCacheManager;
import com.tbynet.jwp.service.support.TermResponseBuilder;
import com.tbynet.jwp.repository.dto.result.TermResult;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * 批量删除任务
 * 添加进度监控、错误恢复和性能优化
 */
public class TermBatchDeleteTask implements Callable<TermResponse.BatchOperationResult> {

    private static final Log log = Log.getLog(TermBatchDeleteTask.class);

    private final List<BigInteger> termIds;
    private final String taxonomy;
    private final List<TermResult> preFetchedTerms;
    private final TermCacheManager cacheManager;

    // 进度监控
    private volatile int processedCount = 0;
    private volatile int successCount = 0;
    private final Date startTime;

    public TermBatchDeleteTask(List<BigInteger> termIds, String taxonomy,
                               List<TermResult> preFetchedTerms, TermCacheManager cacheManager) {
        this.termIds = termIds != null ? new ArrayList<>(termIds) : new ArrayList<>();
        this.taxonomy = taxonomy;
        this.preFetchedTerms = preFetchedTerms != null ? new ArrayList<>(preFetchedTerms) : new ArrayList<>();
        this.cacheManager = cacheManager;
        this.startTime = new Date();
    }

    @Override
    public TermResponse.BatchOperationResult call() {
        if (termIds.isEmpty() || StrKit.isBlank(taxonomy)) {
            log.error("批量删除分类项参数错误");
            return TermResponseBuilder.buildEmptyBatchResult();
        }

        List<BigInteger> successIds = new ArrayList<>();
        List<BigInteger> failedIds = new ArrayList<>();
        List<String> errorMessages = new ArrayList<>();

        log.info("开始执行优化的批量删除后缓存清理，分类项数量: %s, taxonomy: %s", termIds.size(), taxonomy);

        // 分批处理配置
        int batchSize = 50;
        int delayBetweenBatches = 10; // 毫秒

        for (int i = 0; i < termIds.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, termIds.size());
            List<BigInteger> batch = termIds.subList(i, endIndex);

            // 处理当前批次
            processBatch(batch, successIds, failedIds, errorMessages);
            processedCount = endIndex;

            // 批次间延迟
            if (endIndex < termIds.size()) {
                try {
                    Thread.sleep(delayBetweenBatches);
                } catch (InterruptedException e) {
                    log.warn("批量删除任务被中断");
                    Thread.currentThread().interrupt();
                    break;
                }
            }

            // 进度日志
            if (endIndex % 100 == 0 || endIndex == termIds.size()) {
                log.info("批量删除缓存清理进度: %s/%s, 成功: %s, 失败: %s",
                        endIndex, termIds.size(), successIds.size(), failedIds.size());
            }
        }

        // 清理全局缓存
        cleanGlobalCache();

        // 性能统计
        long duration = System.currentTimeMillis() - startTime.getTime();
        log.info("批量删除后缓存清理完成: 总数=%s, 成功=%s, 失败=%s, 耗时=%sms, taxonomy=%s",
                termIds.size(), successIds.size(), failedIds.size(), duration, taxonomy);

        return TermResponseBuilder.buildBatchResult(termIds, taxonomy, successIds, failedIds, errorMessages, duration);
    }

    /**
     * 处理单个批次
     */
    private void processBatch(List<BigInteger> batch, List<BigInteger> successIds,
                              List<BigInteger> failedIds, List<String> errorMessages) {
        for (BigInteger termId : batch) {
            try {
                TermResult termInfo = findPreFetchedTerm(termId);

                if (termInfo != null) {
                    // 使用优化的缓存清理
                    cacheManager.optimizedComprehensiveClean(termId, taxonomy, termInfo);
                    successIds.add(termId);
                    successCount++;

                    log.debug("清理分类项缓存成功: termId=%s", termId);
                } else {
                    // 没有预获取信息，使用保守清理
                    cacheManager.removeTermCache(termId, taxonomy);
                    failedIds.add(termId);
                    errorMessages.add("未找到分类项信息: " + termId);
                    log.warn("未找到分类项信息，使用保守清理: termId=%s", termId);
                }
            } catch (Exception e) {
                failedIds.add(termId);
                String errorMsg = String.format("清理分类项缓存异常: termId=%s, error=%s",
                        termId, e.getMessage());
                errorMessages.add(errorMsg);
                log.error("清理分类项缓存异常: termId=%s", termId, e);
            }
        }
    }

    /**
     * 查找预获取的分类项信息
     */
    private TermResult findPreFetchedTerm(BigInteger termId) {
        return preFetchedTerms.stream()
                .filter(term -> term != null && termId.equals(term.getTermId()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 清理全局缓存
     */
    private void cleanGlobalCache() {
        try {
            long start = System.currentTimeMillis();

            // 1. 清理根层级缓存
            cacheManager.removeHierarchyCache(taxonomy, null);

            // 2. 清理分类法统计缓存
            cacheManager.removeTaxonomyCache("statistics:" + taxonomy);

            // 3. 智能缓存预热
            cacheManager.intelligentPreload(taxonomy, 20);

            long duration = System.currentTimeMillis() - start;
            log.debug("全局缓存清理完成，耗时: %sms", duration);

        } catch (Exception e) {
            log.error("清理全局缓存失败", e);
        }
    }



    /**
     * 获取任务进度（用于监控）
     */
    public Map<String, Object> getProgress() {
        Map<String, Object> progress = new HashMap<>();
        progress.put("total", termIds.size());
        progress.put("processed", processedCount);
        progress.put("success", successCount);
        progress.put("failed", processedCount - successCount);
        progress.put("startTime", startTime);
        progress.put("taxonomy", taxonomy);

        if (processedCount > 0) {
            double percentage = (double) processedCount / termIds.size() * 100;
            progress.put("percentage", String.format("%.1f%%", percentage));

            long elapsed = System.currentTimeMillis() - startTime.getTime();
            if (processedCount > 0) {
                long estimatedTotal = elapsed * termIds.size() / processedCount;
                long remaining = estimatedTotal - elapsed;
                progress.put("estimatedRemainingMs", remaining);
            }
        }

        return progress;
    }
}